package cn.tedu.smartos.family_user.service.impl;

import cn.tedu.smartos.base.exception.ServiceException;
import cn.tedu.smartos.base.response.StatusCode;
import cn.tedu.smartos.family_user.mapper.ElectronicFenceMapper;
import cn.tedu.smartos.family_user.mapper.LocationRecordMapper;
import cn.tedu.smartos.family_user.pojo.entity.ElectronicFence;
import cn.tedu.smartos.family_user.pojo.entity.LocationRecord;
import cn.tedu.smartos.family_user.pojo.vo.LocationRecordVO;
import cn.tedu.smartos.family_user.service.ElderlyBindService;
import cn.tedu.smartos.family_user.service.LocationService;
import cn.tedu.smartos.family_user.service.PositionAlertService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class LocationServiceImpl implements LocationService {
    @Autowired
    private LocationRecordMapper locationRecordMapper;

    @Autowired
    private ElderlyBindService elderlyBindService;

    @Autowired
    private PositionAlertService positionAlertService;

    @Autowired
    private ElectronicFenceMapper electronicFenceMapper;

    @Override
    public LocationRecordVO getLatestLocation(Long elderlyUserId) {
        // 获取最新位置记录
        LocationRecord record = locationRecordMapper.selectLatestByElderlyUserId(elderlyUserId);

        if (record == null) {
            throw new ServiceException(StatusCode.FAILED, "未找到位置记录");
        }

        // 转换为VO
        LocationRecordVO vo = new LocationRecordVO();
        BeanUtils.copyProperties(record, vo);
        return vo;
    }

    @Override
    public List<LocationRecordVO> getLocationHistory(Long elderlyUserId, Integer limit) {
        // 默认查询最近10条记录
        if (limit == null || limit <= 0) {
            limit = 10;
        }

        // 获取位置历史
        List<LocationRecord> records = locationRecordMapper.selectHistoryByElderlyUserId(elderlyUserId, limit);

        // 转换为VO列表
        return records.stream().map(record -> {
            LocationRecordVO vo = new LocationRecordVO();
            BeanUtils.copyProperties(record, vo);
            return vo;
        }).collect(Collectors.toList());
    }

    @Transactional
    @Override
    public void addLocationRecord(LocationRecord record) {
        // 1. 参数校验
        if (record.getElderlyUserId() == null) {
            throw new ServiceException(StatusCode.INVALID_REQUEST, "老人ID不能为空");
        }
        if (record.getLatitude() == null || record.getLongitude() == null) {
            throw new ServiceException(StatusCode.INVALID_REQUEST, "经纬度不能为空");
        }

        // 2. 补全时间
        record.setUploadTime(new Date());
        // 如果没有 recordTime，也默认当前时间
        if (record.getRecordTime() == null) {
            record.setRecordTime(new Date());
        }

        // 3. 地址字段：保持为空或自定义，**不调用百度**
        //    如需调用百度逆地址解析，在下一行自行实现即可


        // 4. 入库
        locationRecordMapper.insertLocationRecord(record);
        log.info("保存位置记录: 老人ID={}, 记录ID={}, lat={}, lng={}",
                record.getElderlyUserId(), record.getRecordId(), record.getLatitude(), record.getLongitude());

        // 5. 电子围栏越界检测（已有逻辑，无需改动）
        checkBoundaryAlerts(record);
    }

    /**
     * 检测位置是否越出电子围栏
     * @param record 位置记录
     */
    private void checkBoundaryAlerts(LocationRecord record) {
        // 获取老人所有启用的电子围栏
        List<ElectronicFence> fences = electronicFenceMapper.selectActiveFences(record.getElderlyUserId());
        if (fences.isEmpty()) {
            log.debug("老人ID={}没有启用电子围栏", record.getElderlyUserId());
            return;
        }

        // 获取所有绑定该老人的家属
        List<Long> familyUserIds = elderlyBindService.getFamilyUserIdsByElderlyId(record.getElderlyUserId());
        if (familyUserIds.isEmpty()) {
            log.warn("老人ID={}未绑定任何家属", record.getElderlyUserId());
            return;
        }

        for (ElectronicFence fence : fences) {
            // 计算当前位置与围栏中心的距离
            double distance = calculateDistance(
                    fence.getCenterLatitude().doubleValue(),
                    fence.getCenterLongitude().doubleValue(),
                    record.getLatitude().doubleValue(),
                    record.getLongitude().doubleValue()
            );

            log.debug("围栏ID={}, 距离={}米, 半径={}米",
                    fence.getFenceId(), distance, fence.getRadius());

            // 如果在围栏外且上次状态在围栏内（状态变化时报警）
            if (distance > fence.getRadius() && fence.getLastStatus() == 0) {
                String alertContent = String.format("老人已离开%s围栏安全区域", fence.getFenceName());

                // 为每个绑定家属创建预警
                for (Long familyUserId : familyUserIds) {
                    positionAlertService.createBoundaryAlert(
                            record.getElderlyUserId(),
                            familyUserId,
                            fence.getFenceId(),
                            record.getRecordId(),
                            alertContent
                    );
                }

                // 更新围栏状态
                electronicFenceMapper.updateFenceStatus(fence.getFenceId(), 1);
                log.info("检测到围栏越界: 围栏ID={}, 老人ID={}", fence.getFenceId(), record.getElderlyUserId());
            }
            // 如果在围栏内且上次状态在围栏外
            else if (distance <= fence.getRadius() && fence.getLastStatus() == 1) {
                // 更新围栏状态（进入安全区域）
                electronicFenceMapper.updateFenceStatus(fence.getFenceId(), 0);
                log.info("老人返回安全区域: 围栏ID={}, 老人ID={}", fence.getFenceId(), record.getElderlyUserId());
            }
        }
    }

    /**
     * 使用Haversine公式计算两点间距离（单位：米）
     * @param lat1 纬度1
     * @param lon1 经度1
     * @param lat2 纬度2
     * @param lon2 经度2
     * @return 距离（米）
     */
    private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int R = 6371; // 地球半径（千米）

        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);

        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);

        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return R * c * 1000; // 转换为米
    }
}